/**
 * 所有版权归 广西梧州 陈锦韬 所有
 *
 * @Title: RxHandlerMethod
 * @Package com.rx.core.handler
 * @Description: 函数处理器
 * @author: 陈锦韬
 * @date: 2021\6\11 0011
 * @version V1.0
 * @Copyright: 2021 陈锦韬  All rights reserved.
 */
package com.rx.core.handler;

import com.rx.core.enm.HANDLER_TYPE;
import com.rx.core.enm.RX_LOG_MODE;
import com.rx.core.util.EmptyChecker;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author: Administrator
 * @Description: 函数处理器
 * @date: 2021\6\11 0011
 */
@Data
@Slf4j
abstract public class AbstractHandler implements RxHandlerWraper{
    /**
     * 基本优先级
     */
    protected int order = 0;

    protected String name;
    /**
     * 根据具体的url 设置优先级
     */
    protected Map<String,Integer> orderMap = new HashMap<>();
    /**
     * 本处理器在哪几个模式里存在
     */
    protected Map<HANDLER_TYPE,List<String>> handlerTypeMap = new HashMap<>();

    protected volatile boolean casOrderLock = false;
    protected volatile boolean casTypeLock = false;
    protected ReentrantLock orderLock = new ReentrantLock();
    protected ReentrantLock typeLock = new ReentrantLock();

    AbstractHandler(){

    }
    protected void init(int order,String name){
        this.order = order;
        this.name = name;
        log.info(RX_LOG_MODE.HANDLER_INFO.getFormat("创建 => {}"),this.name);
    }

    private int orderWithoutLock(String key){
        if (EmptyChecker.notEmpty(orderMap)){
            Integer result = orderMap.get(key);
            if (EmptyChecker.notEmpty(result)){
                return result;
            }
        }
        return order;
    }
    @Override
    public int order(String key) {
        if (casOrderLock){
            try{
                orderLock.lock();
                return orderWithoutLock(key);
            }finally {
                orderLock.unlock();
            }
        }else{
            // 平时查询不上锁。
            return orderWithoutLock(key);
        }
    }

    @Override
    public void order(String key, int order) {
        try{
            casOrderLock = true;
            orderLock.lock();
            if (EmptyChecker.isEmpty(orderMap)){
                orderMap = new HashMap<>();
            }
            orderMap.put(key,order);
        }finally {
            orderLock.unlock();
            casOrderLock = false;
        }
    }

    @Override
    public void removeOrder(String key) {
        try{
            casOrderLock = true;
            orderLock.lock();
            orderMap.remove(key);
        }finally {
            orderLock.unlock();
            casOrderLock = false;
        }
    }

    private List<String> getListNotNull(HANDLER_TYPE newType){
        List<String> urlList = handlerTypeMap.get(newType);
        if (EmptyChecker.isEmpty(urlList)){
            urlList = new ArrayList<>();
        }
        return urlList;
    }

    @Override
    public void setHandlerType(HANDLER_TYPE newType,String[] keys) {
        try{
            casTypeLock = true;
            typeLock.lock();
            List<String> urlList = getListNotNull(newType);
            // 合并
            urlList.addAll(Arrays.asList(keys));
            // 去重。
            handlerTypeMap.put(newType,urlList.stream().distinct().collect(Collectors.toList()));
        }finally {
            typeLock.unlock();
            casTypeLock = false;
        }
    }

    @Override
    public void setHandlerType(HANDLER_TYPE newType, String key) {
        try{
            casTypeLock = true;
            typeLock.lock();
            List<String> urlList = getListNotNull(newType);
            // 合并
            urlList.add(key);
            // 去重。
            handlerTypeMap.put(newType,urlList.stream().distinct().collect(Collectors.toList()));
        }finally {
            typeLock.unlock();
            casTypeLock = false;
        }
    }

    @Override
    public void removeHandlerType(HANDLER_TYPE removeType, String key) {
        try{
            casTypeLock = true;
            typeLock.lock();
            List<String> list = handlerTypeMap.get(removeType);
            if (EmptyChecker.isEmpty(list)){
                return;
            }
            list.remove(key);
            if(EmptyChecker.isEmpty(list)){
                handlerTypeMap.remove(removeType);
            }
        }finally {
            typeLock.unlock();
            casTypeLock = false;
        }
    }

    @Override
    public List<HANDLER_TYPE> handlerTypes() {
        if(casTypeLock){
            try{
                typeLock.lock();
                return handlerTypeMap.keySet().stream().collect(Collectors.toList());
            }finally {
                typeLock.unlock();
            }
        }else {
            return handlerTypeMap.keySet().stream().collect(Collectors.toList());
        }

    }

    @Override
    public List<String> handlerType(HANDLER_TYPE keyType) {
        if(casTypeLock){
            try{
                typeLock.lock();
                return getListNotNull(keyType);
            }finally {
                typeLock.unlock();
            }
        }else {
            return getListNotNull(keyType);
        }
    }

    @Override
    public String getHandleName() {
        return name;
    }

}
